﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Linq.Expressions;
using System.Web.Mvc.Html;
using System.Web.Routing;

namespace EventLogger.Web.Helpers
{
    public static class HtmlHelperExtensions
    {
        public static string ActionLink<TController>(this HtmlHelper helper, string linkText, Expression<Func<TController, ActionResult>> action,object htmlAttributes)
            where TController:Controller
        {
            var controllerType = typeof(TController);
            var controllerName = controllerType.Name.Substring(0, controllerType.Name.Length - 10);

            if (!(action.Body is MethodCallExpression))
            {
                throw new NotSupportedException("This lambda is not supported");
            }

            var call = (MethodCallExpression)action.Body;

            var actionName = call.Method.Name;

            var parameters = call.Method.GetParameters();

            var dict = new RouteValueDictionary();

            for (int i = 0; i < parameters.Length; i++)
            {
                var currentArg = call.Arguments[i];

                switch (currentArg.NodeType)
                {
                    case ExpressionType.Constant:
                        dict[parameters[i].Name] = ((ConstantExpression)currentArg).Value;
                        break;
         
                    case ExpressionType.Convert:
                        var expr = currentArg as UnaryExpression;
                        dict[parameters[i].Name] = UnaryExpression.Lambda(expr).Compile().DynamicInvoke();
                        break;

                    default:  
                        var sth = Expression.Lambda<Func<object>>(Expression.Convert(currentArg, typeof(object)), new ParameterExpression[0]);
                        dict[parameters[i].Name] = sth.Compile()();
                        break;
                }  
            }

            IDictionary<string, object> attributes;

            if (htmlAttributes!=null)
            {
                attributes = htmlAttributes.GetType().GetProperties().ToDictionary(p => p.Name, p => p.GetValue(htmlAttributes, null), StringComparer.CurrentCulture); 
            }
            else
            {
                attributes = new Dictionary<string, object>();
            }

            linkText = string.IsNullOrEmpty(linkText) ? "(empty)" : linkText;            

            return helper.ActionLink(linkText, actionName, controllerName, dict, attributes);
        }

        public static string ActionLink<TController>(this HtmlHelper helper, string linkText, Expression<Func<TController, ActionResult>> action)
            where TController : Controller
        {
            return helper.ActionLink<TController>(linkText, action, null);
        }

        public static IEnumerable<int> GetPages(this HtmlHelper helper, int currentPage, int totalPages, int? sidePages)
        {
            sidePages = sidePages ?? 5;

            int startPage = currentPage - (int)sidePages;
            if (startPage < 1)
            {
                startPage = 1;
            }

            int endPage = currentPage + (int)sidePages;
            if (endPage > totalPages)
            {
                endPage = totalPages;
            }

            return Enumerable.Range(startPage, endPage);
        }

        public static IEnumerable<int> GetPages(this HtmlHelper helper, int currentPage, int totalPages)
        {
            return helper.GetPages(currentPage, totalPages, null);

        }
    }
}
